package com.demo.common.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Objects;

/**
 * 加密工具类
 *
 * @author molong
 * @date 2022/8/23
 */
@Slf4j
public class SecurityUtils {

    /**
     * 解密
     *
     * @param dataSecret   数据密钥,16位随机数字字母
     * @param dataSecretIv 数据加密向量,16位随机数字字母
     * @param data         数据
     * @return 解密后数据
     */
    public static String decrypt(String dataSecret, String dataSecretIv, String data) {
        if (StrUtil.isBlank(dataSecret) || StrUtil.isBlank(dataSecretIv) || StrUtil.isBlank(data)) {
            return null;
        }
        try {
            byte[] raw = dataSecret.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(dataSecretIv.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            // 先用base64解密
            byte[] encrypted1 = Base64.getDecoder().decode(data);
            //byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);
            try {
                byte[] original = cipher.doFinal(encrypted1);
                return new String(original, StandardCharsets.UTF_8);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return null;
            }
        } catch (Exception e) {
            log.error("解密失败,", e);
            throw new RuntimeException("解密失败");
        }

    }

    /**
     * 加密
     *
     * @param dataSecret   数据密钥,16位随机数字字母
     * @param dataSecretIv 数据加密向量,16位随机数字字母
     * @param data         数据
     * @return 加密后数据
     */
    public static String encrypt(String dataSecret, String dataSecretIv, Object data) {
        try {
            if (StrUtil.isBlank(dataSecret) || StrUtil.isBlank(dataSecretIv) || Objects.isNull(data)) {
                return null;
            }
            String s = JSONUtil.toJsonStr(data);
            SecretKeySpec secretKeySpec = new SecretKeySpec(dataSecret.getBytes(StandardCharsets.UTF_8), "AES");
            // "算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

            // 使用CBC模式，需要一个向量iv，可增加加密算法的强度
            IvParameterSpec iv = new IvParameterSpec(dataSecretIv.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);

            byte[] encrypted = cipher.doFinal(s.getBytes(StandardCharsets.UTF_8));
            String str = Base64.getEncoder().encodeToString(encrypted);
            //String str = new BASE64Encoder().encode(encrypted);
            return str.replaceAll(System.lineSeparator(), "");
        } catch (Exception e) {
            log.error("加密失败,", e);
            throw new RuntimeException("加密失败");
        }
    }
}
